package top.hmtools.wxmp.webpage.jsSdk;

import java.util.HashMap;
import java.util.TreeMap;

import org.apache.commons.codec.digest.DigestUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import top.hmtools.wxmp.core.configuration.WxmpConfiguration;
import top.hmtools.wxmp.webpage.apis.IJsSdkApi;
import top.hmtools.wxmp.webpage.tools.MapTools;
import top.hmtools.wxmp.webpage.tools.RandomStringTools;

public class JsSdkTools {
	
	private final Logger logger = LoggerFactory.getLogger(JsSdkTools.class);

	/**
	 * jsapi_ticket是公众号用于调用微信JS接口的临时票据。正常情况下，jsapi_ticket的有效期为7200秒，通过access_token来获取。由于获取jsapi_ticket的api调用次数非常有限，频繁刷新jsapi_ticket会导致api调用受限，影响自身业务，开发者必须在自己的服务全局缓存jsapi_ticket 。
	 */
	private static JsapiTicketResult jsapiTicketResult;
	
	private IJsSdkApi jsSdkApi;
	
	private WxmpConfiguration wxmpConfiguration;
	
	/**
	 * 获取用于生成签名用的jsapi_ticket，并缓存到本地内存。
	 * <br><b>注意：只是缓存到本地运行内存</b>
	 * @return
	 */
	public JsapiTicketResult getJsapiTicketResult(){
		if(this.jsSdkApi == null){
			throw new RuntimeException("请执行本对象实例的 setJsSdkApi()方法设置 top.hmtools.wxmp.webpage.apis.IJsSdkApi 接口的对象实例");
		}
		//?access_token=ACCESS_TOKEN&type=jsapi
		//如果缓存的jsapi ticket不为null
		if(jsapiTicketResult !=null){
			//如果缓存的jsapi ticket 没有过期
			if(!jsapiTicketResult.isExpiresOut()){
				return jsapiTicketResult;
			}
		}
		
		//重新获取
		synchronized (JsapiTicketResult.class) {
			HashMap<String, String> params = new HashMap<>();
			params.put("type", "jsapi");
			//缓存到本地
			jsapiTicketResult = jsSdkApi.getTicket();
		}
		return jsapiTicketResult;
	}
	
	/**
	 * 生成前端js页面初始化时所需要的config数据
	 * @param urlStr
	 * @param eSignType
	 * @return
	 */
	public JsConfigVO getJsConfig(String urlStr,ESignType eSignType){
		if(this.wxmpConfiguration == null || this.wxmpConfiguration.getAppid() == null){
			throw new RuntimeException("请设置本对象实例的 top.hmtools.wxmp.webpage.jsSdk.JsSdkTools.wxmpConfiguration 属性值");
		}
		JsConfigVO result = new JsConfigVO();
		
		String appid = this.wxmpConfiguration.getAppid();
		result.setAppId(appid);
		result.setNonceStr(RandomStringTools.getGenerateShortUuid(16));
		result.setTimestamp(System.currentTimeMillis()/1000);
		result.setUrl(urlStr);
		result.setUrlInSignature(urlStr.split("#")[0]);
		
		if(this.logger.isDebugEnabled()){
			this.logger.debug("参与计算签名的原始参数：{}",result);
		}
		
		//获取签名
		String signature = null;
		//组装签名用参数
		TreeMap<String, String> tm = new TreeMap<>();
		tm.put("noncestr", result.getNonceStr());
		tm.put("jsapi_ticket", this.getJsapiTicketResult().getTicket());
		tm.put("timestamp", String.valueOf(result.getTimestamp()));
		tm.put("url", result.getUrlInSignature());
		String orderDictStr = MapTools.getOrderDictStr(tm, "=", "&");
		
		if(this.logger.isDebugEnabled()){
			this.logger.debug("参与计算签名的参数排序后字符串：{}",orderDictStr);
		}
		
		if(eSignType == null){
			eSignType = ESignType.SHA1;
		}
		switch (eSignType) {
		case MD5:
			signature = DigestUtils.md5Hex(orderDictStr).toLowerCase();
			break;
		default:
			signature = DigestUtils.sha1Hex(orderDictStr).toLowerCase();
			break;
		}
		
		result.setSignature(signature);
		
		if(this.logger.isDebugEnabled()){
			this.logger.debug("最终的js-sdk config数据是：{}",result);
		}
		return result;
	}

	public IJsSdkApi getJsSdkApi() {
		return jsSdkApi;
	}

	public void setJsSdkApi(IJsSdkApi jsSdkApi) {
		this.jsSdkApi = jsSdkApi;
	}

	public WxmpConfiguration getWxmpConfiguration() {
		return wxmpConfiguration;
	}

	public void setWxmpConfiguration(WxmpConfiguration wxmpConfiguration) {
		this.wxmpConfiguration = wxmpConfiguration;
	}
	
	
	
	
	
	
	
	
	
	
	
	
	
	
}
